.\"	$NetBSD$
.\"
.\" Copyright (c) 2011-2019 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This material is based upon work partially supported by The
.\" NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd August 25, 2019
.Dt LIBNPF 3
.Os
.Sh NAME
.Nm libnpf
.Nd NPF packet filter library
.Sh LIBRARY
.Lb libnpf
.Sh SYNOPSIS
.In npf.h
.\" ---
.Ft nl_config_t *
.Fn npf_config_create "void"
.Ft int
.Fn npf_config_submit "nl_config_t *ncf" "int fd" "npf_error_t *errinfo"
.Ft nl_config_t *
.Fn npf_config_retrieve "int fd"
.Ft int
.Fn npf_config_flush "int fd"
.Ft void
.Fn npf_config_export "nl_config_t *ncf" "size_t *len"
.Ft nl_config_t *
.Fn npf_config_import "const void *blob" "size_t len"
.Ft bool
.Fn npf_config_active_p "nl_config_t *ncf"
.Ft bool
.Fn npf_config_loaded_p "nl_config_t *ncf"
.Ft void
.Fn npf_config_destroy "nl_config_t *ncf"
.\" ---
.Ft nl_rule_t *
.Fn npf_rule_create "const char *name" "uint32_t attr" "const char *ifname"
.Ft int
.Fn npf_rule_setcode "nl_rule_t *rl" "int type" "const void *code" "size_t len"
.Ft int
.Fn npf_rule_setkey "nl_rule_t *rl" "const void *key" "size_t len"
.Ft int
.Fn npf_rule_setinfo "nl_rule_t *rl" "const void *info" "size_t len"
.Ft int
.Fn npf_rule_setprio "nl_rule_t *rl" "int pri"
.Ft int
.Fn npf_rule_setproc "nl_rule_t *rl" "const char *name"
.Ft int
.Fn npf_rule_insert "nl_config_t *ncf" "nl_rule_t *parent" "nl_rule_t *rl"
.Ft bool
.Fn npf_rule_exists_p "nl_config_t *ncf" "const char *name"
.Ft void *
.Fn npf_rule_export "nl_rule_t *rl" "size_t *length"
.Ft void
.Fn npf_rule_destroy "nl_rule_t *rl"
.\" ---
.Ft nl_rproc_t *
.Fn npf_rproc_create "const char *name"
.Ft int
.Fn npf_rproc_extcall "nl_rproc_t *rp" "nl_ext_t *ext"
.Ft bool
.Fn npf_rproc_exists_p "nl_config_t *ncf" "const char *name"
.Ft int
.Fn npf_rproc_insert "nl_config_t *ncf" "nl_rproc_t *rp"
.\" ---
.Ft nl_nat_t *
.Fn npf_nat_create "int type" "unsigned flags" "const char *ifname"
.Ft int
.Fn npf_nat_setaddr "nl_nat_t *nt" "int af" "npf_addr_t *addr" \
"npf_netmask_t mask"
.Ft int
.Fn npf_nat_setport "nl_nat_t *nt" "in_port_t port"
.Ft int
.Fn npf_nat_insert "nl_config_t *ncf" "nl_nat_t *nt"
.\" ---
.Ft nl_table_t *
.Fn npf_table_create "const char *name" "unsigned id" "int type"
.Ft int
.Fn npf_table_add_entry "nl_table_t *tl" "int af" \
"const npf_addr_t *addr" "const npf_netmask_t mask"
.Ft int
.Fn npf_table_insert "nl_config_t *ncf" "nl_table_t *tl"
.Ft int
.Fn npf_table_replace "int fd" "nl_table_t *tl" "npf_error_t *errinfo"
.Ft void
.Fn npf_table_destroy "nl_table_t *tl"
.\" ---
.Ft int
.Fn npf_ruleset_add "int fd" "const char *name" "nl_rule_t *rl" "uint64_t *id"
.Ft int
.Fn npf_ruleset_remove "int fd" "const char *name" "uint64_t id"
.Ft int
.Fn npf_ruleset_remkey "int fd" "const char *name" "const void *key" "size_t len"
.Ft int
.Fn npf_ruleset_flush "int fd" "const char *name"
.\" -----
.Sh DESCRIPTION
The
.Nm
library provides an interface to create an NPF configuration having rules,
tables, procedures, or translation policies.
The configuration can be submitted to the kernel.
.\" -----
.Sh FUNCTIONS
.Ss Configuration
.Bl -tag -width 4n
.It Fn npf_config_create
Create a new configuration object.
.It Fn npf_config_submit "ncf" "fd" "errinfo"
Submit the configuration object, specified by
.Fa ncf ,
to the kernel.
On failure, the error information is written into the structure
specified by
.Fa errinfo .
.It Fn npf_config_export "ncf" "len"
Serialize the given configuration and return the binary object as
well as its length in
.Fa len
parameter.
The binary object is dynamically allocated and should be destroyed using
.Xr free 3 .
.It Fn npf_config_import "blob" "len"
Read the configuration from a binary object of the specified length,
unserialize, and return the configuration object.
.It Fn npf_config_flush "fd"
Flush the current configuration.
.It Fn npf_config_retrieve "fd"
Retrieve and return the loaded configuration from the kernel.
.It Fn npf_config_active_p "ncf"
Indicate whether the retrieved configuration is active i.e. packet
filtering is enabled (true if yes and false otherwise).
.It Fn npf_config_loaded_p "ncf"
Indicate whether the retrieved configuration is loaded i.e. has any
rules (true if yes and false otherwise).
.It Fn npf_config_destroy "ncf"
Destroy the configuration object, specified by
.Fa ncf .
.El
.\" ---
.Ss Rule interface
.Bl -tag -width 4n
.It Fn npf_rule_create "name" "attr" "ifname"
Create a rule with a given name, attributes and priority.
If the name is specified, then it should be unique within the
configuration object.
Otherwise, the name can be
.Dv NULL ,
in which case the rule will have no identifier.
The following attributes, which can be ORed, are available:
.Bl -tag -width indent
.It Dv NPF_RULE_PASS
The decision of this rule shall be "pass".
If this attribute is not
specified, then "block" (drop the packet) is the default.
.It Dv NPF_RULE_IN
Match the incoming packets.
.It Dv NPF_RULE_OUT
Match the outgoing packets.
.It Dv NPF_RULE_FINAL
Indicate that on rule match, further processing of the ruleset should
be stopped and this rule should be applied instantly.
.It Dv NPF_RULE_STATEFUL
Create a state (session) on match, track the connection and pass the
backwards stream (the returning packets) without the ruleset inspection.
The state is uniquely identified by an n-tuple key.
.It Dv NPF_RULE_GSTATEFUL
Exclude the interface identifier from the state key (n-tuple).
This makes the state global with respect to the network interfaces.
The state is also picked for packets travelling in different direction
than originally.
.It Dv NPF_RULE_RETRST
Return TCP RST packet in a case of packet block.
.It Dv NPF_RULE_RETICMP
Return ICMP destination unreachable in a case of packet block.
.It Dv NPF_RULE_GROUP
Allow this rule to have sub-rules.
If this flag is used with the
.Dv NPF_RULE_DYNAMIC
flag set, then it is a dynamic group.
The sub-rules can be added dynamically to a dynamic group, also meaning
that the sub-rules must have the
.Dv NPF_RULE_DYNAMIC
flag set.
Otherwise rules must be added statically i.e. created with the configuration.
.It Dv NPF_RULE_DYNAMIC
Indicate that the rule is dynamic.
Such rules can only be added to the dynamic groups.
.El
.Pp
The interface is specified by the
.Fa ifname
string.
.Dv NULL
indicates any interface.
.\" ---
.It Fn npf_rule_setcode "rl" "type" "code" "len"
Assign the code for the rule specified by
.Fa rl .
The code is used to implement the filter criteria.
The pointer to the binary code is specified by
.Fa code ,
the size of the memory area by
.Fa len ,
and the type of the code is specified by
.Fa type .
Currently, only the BPF byte-code is supported and the
.Dv NPF_CODE_BPF
constant should be passed.
.\" ---
.It Fn npf_rule_setkey "rl" "key" "len"
Assign a key for the rule specified by
.Fa rl .
The binary key is specified by
.Fa key ,
and its size by
.Fa len .
The size shall not exceed
.Dv NPF_RULE_MAXKEYLEN .
The kernel does not check whether key is unique, therefore it is the
responsibility of the caller.
.\" ---
.It Fn npf_rule_setinfo "rl" "info" "len"
Associate an arbitrary information blob specified by
.Fa info ,
and its size by
.Fa len .
This may be used for such purposes as the byte-code annotation.
.\" ---
.It Fn npf_rule_setprio "rl" "pri"
Set priority to the rule.
Negative priorities are invalid.
.Pp
The priority is the order of the rule in the ruleset.
The lower value means first to process, the higher value - last to process.
If multiple rules are inserted with the same priority,
then the order is unspecified.
.Pp
The special constants
.Dv NPF_PRI_FIRST
and
.Dv NPF_PRI_LAST
can be passed to indicate that the rule should be inserted into the
beginning or the end of the priority level 0 in the ruleset.
All rules inserted using these constants will have the priority 0
assigned and will share this level in the ordered way.
.\" ---
.It Fn npf_rule_setproc "rl" "name"
Set a procedure for the specified rule.
.\" ---
.It Fn npf_rule_insert "ncf" "parent" "rl"
Insert the rule into the set of the parent rule specified by
.Fa parent .
If the value of
.Fa parent
is
.Dv NULL ,
then insert into the main ruleset.
The rule will be consumed (the relevant resourced will be freed) and it
must not be referenced after insertion.
.\" ---
.It Fn npf_rule_exists_p "ncf" "name"
Check whether the rule with a given name is already in the configuration.
.\" ---
.It Fn npf_rule_export "rl" "length"
Serialize the rule (including the byte-code), return a binary object
and set its
.Fa length .
The binary object is dynamically allocated and should be destroyed using
.Xr free 3 .
.\" ---
.It Fn npf_rule_destroy "rl"
Destroy the given rule object.
.El
.\" -----
.Ss Rule procedure interface
.Bl -tag -width 4n
.It Fn npf_rproc_create "name"
Create a rule procedure with a given
.Fa name .
Thr name must be unique for each procedure.
.It Fn npf_rproc_insert "ncf" "rp"
Insert the rule procedure into the specified configuration object.
The rule procedure must not be referenced after insertion.
.El
.\" -----
.Ss Translation interface
.Bl -tag -width 4n
.It Fn npf_nat_create "type" "flags" "ifname"
Create a NAT policy of a specified type.
There are two types:
.Bl -tag -width "NPF_NAT_PORTMAP "
.It Dv NPF_NATIN
Inbound NAT policy (rewrite destination).
.It Dv NPF_NATOUT
Outbound NAT policy (rewrite source).
.El
.Pp
A bi-directional NAT is obtained by combining two policies.
The following
.Fa flags
are supported:
.Bl -tag -width "NPF_NAT_PORTMAP "
.It Dv NPF_NAT_STATIC
Perform static (stateless) translation rather than dynamic (stateful).
.It Dv NPF_NAT_PORTS
Perform the port translation.
If this flag is not specified, then the port translation is not performed
and the
.Fa port
parameter is ignored.
.It Dv NPF_NAT_PORTMAP
Create a port map and select a random port for translation.
If enabled, then the value specified by the
.Fa port
parameter is ignored.
This flag is effective only if the
.Dv NPF_NAT_PORTS
flag is set.
.El
.Pp
The network interface on which the policy will be applicable is specified by
.Fa ifname .
.\" ---
.It Fn npf_nat_setaddr "nt" "af" "addr" "mask"
Set the translation address, as specified by
.Fa addr ,
and its family by
.Fa af .
The family must be either
.Dv AF_INET
for IPv4 or
.Dv AF_INET6
for IPv6 address.
Additionally,
.Fa mask
may be specified to indicate the translation network;
otherwise, it should be set to
.Dv NPF_NO_NETMASK .
.Pp
In order to use the translation network, a custom algorithm may need to
be specified using the
.Fn npf_nat_setalgo
function.
.\" ---
.It Fn npf_nat_setport "nt" "port"
Set the translation port, specified by
.Fa port .
.\" ---
.It Fn npf_nat_setalgo "nt" "algo"
Set a particular NAT algorithm.
Currently, the following algorithms are supported with dynamic NAT:
.Bl -tag -width "NPF_ALGO_IPHASH"
.It Dv NPF_ALGO_IPHASH
Hash of the source and destination addresses.
.It Dv NPF_ALGO_RR
Round-robin for the translation addresses.
.It Dv NPF_ALGO_NETMAP
Network-to-network map as described below, but with state tracking.
It is used when it is necessary to translate the ports.
.El
.Pp
The following are support with static NAT:
.Bl -tag -width "NPF_ALGO_NETMAP"
.It Dv NPF_ALGO_NETMAP
Network-to-network map where the translation network prefix (address
after applying the mask) is bitwise OR-ed with the host part of the
original address (zero bits of the mask).
.It Dv NPF_ALGO_NPT66
IPv6-to-IPv6 Network Prefix Translation (NPTv6, defined in RFC 6296).
.El
.\" ---
.It Fn npf_nat_insert "ncf" "nt"
Insert the NAT policy, its rule, into the specified configuration.
The NAT rule must not be referenced after insertion.
.El
.\" -----
.Ss Table interface
.Bl -tag -width 4n
.It Fn npf_table_create "name" "index" "type"
Create an NPF table of a specified type.
The table is identified by the
.Fa name
and
.Fa index ,
which should be in the range between 1 and
.Dv NPF_MAX_TABLES .
.Pp
The following types are supported:
.Bl -tag -width "NPF_TABLE_IPSET"
.It Dv NPF_TABLE_IPSET
Indicates to use a regular associative array for storage of IP sets.
Currently implemented as a hashmap.
.It Dv NPF_TABLE_LPM
Indicates to the table can contain networks (as well as hosts) and the
longest prefix match should be performed on lookup.
.It Dv NPF_TABLE_CONST
Indicates that the table contents will be constant and the table can be
considered immutable (no inserts/removes after load).
If such constraint is acceptable, this table type will provide the best
performance.
It is currently implemented as a perfect hash table, generated on table
insertion into the configuration.
.El
.\" ---
.It Fn npf_table_add_entry "tl" "af" "addr" "mask"
Add an entry of IP address and mask, specified by
.Fa addr
and
.Fa mask ,
to the table specified by
.Fa tl .
The family, specified by
.Fa af ,
must be either
.Dv AF_INET
for IPv4 or
.Dv AF_INET6
for IPv6 address.
If there is no mask, then
.Fa mask
should be set to
.Dv NPF_NO_NETMASK .
.\" ---
.It Fn npf_table_insert "ncf" "tl"
Add the table to the configuration object.
This routine performs a check for duplicate table IDs.
The table must not be referenced after insertion.
.\" ---
.It Fn npf_table_replace "fd" "tl" "errinfo"
Submit the table object, specified by
.Fa tl ,
to the kernel, to replace the existing table with the
corresponding table name and ID.
On failure, the error information is written into the structure
specified by
.Fa errinfo .
.\" ---
.It Fn npf_table_destroy "tl"
Destroy the specified table.
.El
.\" -----
.Ss Ruleset interface
.Bl -tag -width 4n
.It Fn npf_ruleset_add "fd" "name" "rl" "id"
Add a given rule, specified by
.Fa rl ,
into the dynamic ruleset named
.Fa name .
On success, return 0 and a unique rule ID in the
.Fa id
parameter.
.It Fn npf_ruleset_remove "fd" "name" "id"
Remove a rule from the dynamic ruleset, specified by
.Fa name .
The rule is specified by its unique ID in the
.Fa id
parameter.
.It Fn npf_ruleset_remkey "fd" "name" "key" "len"
Remove a rule from the dynamic ruleset, specified by
.Fa name .
The rule is specified by its key, in the
.Fa key
and
.Fa len
parameters.
The key for the rule must have been set during its construction, using the
.Fn npf_rule_setkey
routine.
.It Fn npf_ruleset_flush "fd" "name"
Clear the dynamic ruleset, specified by
.Fa name ,
by removing all its rules.
.El
.\" -----
.Sh SEE ALSO
.Xr bpf 4 ,
.Xr npf 7 ,
.Xr npfctl 8
.Sh HISTORY
The NPF library first appeared in
.Nx 6.0 .
